import {
  Button, message
} from 'antd';
import { ProgressBar } from 'antd-mobile';
import { useSelector, useDispatch } from 'react-redux';
import { useBoolean, useEventEmitter, useRequest } from 'ahooks';
import { useParams, useHistory } from 'react-router-dom';
import { useCallback, useEffect, useState } from 'react';

import {
  Name,
  Num,
  Email,
  Gender,
  MaritalStatus,
  ChildrenSituation,
  Age,
  Education,
  WorkUnit,
  Affiliated,
  JobPosition,
  OperatingPost,
} from './item';

import * as API from '../../../../constants/api-constants';
import { useCheckUserInfoRange, useRouterKeysArr } from './hooks';
import {
  updateUserPropAction,
  initMergeUuidAction,
  initNextEvent
} from '../../actions';
import questionnaireStyle from './style.module.less';

/**
 * 生成组件数组
 * @returns {basicRouteComponentArray} 组件数组
 */
const initBasicRouteComponentArray = (
  userInfo: QA.UserInitBasic,
  onChange: (key: string, value: string | number) => void
) => {
  const {
    name,
    num,
    email,
    gender,
    maritalStatus,
    childrenSituation,
    age,
    education,
    workUnit,
    affiliated,
    jobPosition,
    operatingPost
  } = userInfo;
  const basicRouteComponentArray = [
    {
      name: 'name',
      component: <Name
        value={name}
        onChange={onChange}
      />
    },
    {
      name: 'num',
      component: <Num
        value={num}
        onChange={onChange}
      />
    },
    {
      name: 'email',
      component: <Email
        value={email}
        onChange={onChange}
      />
    },
    {
      name: 'gender',
      component: <Gender
        value={gender}
        onChange={onChange}
      />,
    },
    {
      name: 'maritalStatus',
      component: <MaritalStatus
        value={maritalStatus}
        onChange={onChange}
      />
    },
    {
      name: 'childrenSituation',
      component: <ChildrenSituation
        value={childrenSituation}
        onChange={onChange}
      />
    },
    {
      name: 'age',
      component: <Age
        value={age}
        onChange={onChange}
      />
    },
    {
      name: 'education',
      component: <Education
        value={education}
        onChange={onChange}
      />
    },
    {
      name: 'workUnit',
      component: <WorkUnit
        value={workUnit}
        onChange={onChange}
      />
    },
    {
      name: 'affiliated',
      component: <Affiliated
        value={affiliated}
        onChange={onChange}
      />
    },
    {
      name: 'jobPosition',
      component: <JobPosition
        value={jobPosition}
        onChange={onChange}
      />
    },
    {
      name: 'operatingPost',
      component: <OperatingPost
        value={operatingPost}
        onChange={onChange}
      />
    }
  ];
  return basicRouteComponentArray;
};

/**
 * 生成请求参数
 * @param jobPositionVisible
 * @param affiliatedVisible
 * @param workUnitVisible
 * @param operatingPostVisible
 * @param userInfo
 * @returns {userInfoParam}
 */
const createParamUserInfo = (
  userNameVisible: boolean,
  userNumVisible: boolean,
  jobPositionVisible: boolean,
  affiliatedVisible: boolean,
  workUnitVisible: boolean,
  operatingPostVisible: boolean,
  questionnaireUuid: string,
  userUuid: string,
  userInfo: QA.UserInitBasic
) => {
  const {
    name,
    num,
    email,
    gender,
    maritalStatus,
    childrenSituation,
    age,
    education,
    workUnit,
    affiliated,
    jobPosition,
    operatingPost
  } = userInfo;

  const userBasicParam: QA.UserBasicParamType = {
    gender,
    maritalStatus,
    childrenSituation,
    age,
    education,
    email
  };
  if (userNameVisible) {
    userBasicParam.name = name;
  }
  if (userNumVisible) {
    userBasicParam.num = num;
  }
  if (jobPositionVisible) {
    userBasicParam.jobPosition = jobPosition;
  }
  if (affiliatedVisible) {
    userBasicParam.affiliated = affiliated;
  }
  if (workUnitVisible) {
    userBasicParam.workUnit = workUnit;
  }
  if (operatingPostVisible) {
    userBasicParam.operatingPost = operatingPost;
  }

  const userInfoParam = {
    questionnaireUuid,
    userUuid,
    ...userBasicParam
  };
  return userInfoParam;
};

interface FooterProps {
  userInfo: QA.UserInitBasic,
  routerKeysArr: (keyof QA.UserInitBasic)[],
  questionnaireUuid: string,
  currentRouteIndex: number,
  isInSelectProgress: boolean,
  needSaveBasicInfo: () => void
}

const Footer = ({
  userInfo,
  routerKeysArr,
  questionnaireUuid,
  currentRouteIndex,
  isInSelectProgress,
  needSaveBasicInfo
}: FooterProps) => {
  const exit$ = useEventEmitter();
  const dispatch = useDispatch();
  const [preDisable, {
    setTrue: setPreDisableTrue,
    setFalse: setPreDisableFalse
  }] = useBoolean(false);
  const history = useHistory();
  const routerKeysArrLength = routerKeysArr.length;
  /** 进度百分比 */
  const processPercent = ((currentRouteIndex + 1) / routerKeysArrLength) * 100;
  /** 是否填写最后一项用户信息 */
  const isAnswerLastQuestion = userInfo[
    routerKeysArr[currentRouteIndex]
  ] === undefined;
  const isInProgress = isAnswerLastQuestion || isInSelectProgress;

  // 设置按钮展示状态
  useEffect(() => {
    // 设置“上一项”按钮状态
    if (currentRouteIndex === 0) {
      setPreDisableTrue();
    }
    if (currentRouteIndex !== 0) {
      setPreDisableFalse();
    }
  }, [currentRouteIndex]);

  const handlePutUserInfo = useCallback(() => {
    if (currentRouteIndex === routerKeysArrLength - 1) {
      needSaveBasicInfo();
      return;
    }

    history.push(`/questionAnswer/home/${questionnaireUuid}/basicInfo/${currentRouteIndex + 1}`);
  }, [currentRouteIndex, routerKeysArrLength, questionnaireUuid]);

  const getNextButtonColorStyleObj = useCallback(
    (_isInProgress) => (
      _isInProgress
        ? { color: '#ddd' }
        : undefined
    ),
    []
  );

  const getPreButtonColorStyleObj = useCallback(
    (_preDisable) => (
      _preDisable
        ? { color: '#ddd' }
        : undefined
    ),
    []
  );

  exit$.useSubscription(handlePutUserInfo);

  useEffect(() => {
    dispatch(initNextEvent(exit$));
  }, []);

  return (
    <div className={questionnaireStyle.footer}>
      <ProgressBar
        percent={processPercent}
        style={{
          '--track-width': '5px',
        }}
      />
      <div className={questionnaireStyle['basic-footer']}>
        <Button
          style={getPreButtonColorStyleObj(preDisable)}
          type="link"
          disabled={preDisable}
          onClick={() => {
            history.push(`/questionAnswer/home/${questionnaireUuid}/basicInfo/${currentRouteIndex - 1}`);
          }}
        >
          上一项
        </Button>
        <span className={questionnaireStyle.process}>
          {currentRouteIndex + 1}
          /
          {routerKeysArrLength}
        </span>
        <Button
          style={getNextButtonColorStyleObj(isInProgress)}
          disabled={isInProgress}
          type="link"
          onClick={() => {
            handlePutUserInfo();
          }}
        >
          下一项
        </Button>
      </div>
    </div>
  );
};

const BasicInfo = () => {
  const history = useHistory();
  const dispatch = useDispatch();
  const [
    isNeedSaveBasicInfo,
    {
      setTrue: needSaveBasicInfo,
      setFalse: dontNeedSaveBasicInfo
    }
  ] = useBoolean(false);
  const [isInSelectProgress, setIsInSelectProgress] = useState(false);
  const { index, questionnaireUuid } = useParams<{
    index: string,
    questionnaireUuid: string
  }>();

  const {
    userNameVisible,
    userNumVisible,
    jobPositionVisible,
    affiliatedVisible,
    workUnitVisible,
    operatingPostVisible,
    userUuid,
    userInfo
  } = useSelector((
    storeState: QA.ReduxState
  ) => ({
    userNameVisible: storeState.userNameVisible,
    userNumVisible: storeState.userNumVisible,
    jobPositionVisible: storeState.jobPositionVisible,
    affiliatedVisible: storeState.affiliatedVisible,
    workUnitVisible: storeState.workUnitVisible,
    operatingPostVisible: storeState.operatingPostVisible,
    userUuid: storeState.userUuid,
    userInfo: storeState.userInitBasic
  }));

  /**
   * key数组
   */
  const routerKeysArr = useRouterKeysArr(
    userNameVisible,
    userNumVisible,
    workUnitVisible,
    affiliatedVisible,
    jobPositionVisible,
    operatingPostVisible
  );

  /**
   * 保存用户信息
   */
  const { run } = useRequest((userBasicParam) => {
    const userInfoParam = createParamUserInfo(
      userNameVisible,
      userNumVisible,
      jobPositionVisible,
      affiliatedVisible,
      workUnitVisible,
      operatingPostVisible,
      questionnaireUuid,
      userUuid,
      userBasicParam
    );
    return {
      url: API.USER_INFO,
      method: 'PUT',
      data: {
        ...userInfoParam,
        startTime: Number(new Date())
      },
    };
  }, {
    manual: true,
    onSuccess: (result) => {
      const { mergeUuid } = result.data;
      dispatch(initMergeUuidAction(mergeUuid));
      history.push(`/questionAnswer/home/${questionnaireUuid}/question/${0}`);
    },
    onError: () => {
      message.error('用户信息提交失败');
    },
  });

  /** 当前数组下标 */
  const currentRouteIndex = Number(index);
  const routerKeysArrLength = routerKeysArr.length;

  /** 子组件onChange */
  const onChange = (key: string, value: string | number, isInput?: boolean) => {
    setIsInSelectProgress(true);
    dispatch(updateUserPropAction({
      key,
      value
    }));

    if (currentRouteIndex === routerKeysArrLength - 1) {
      needSaveBasicInfo();
      return;
    }
    setIsInSelectProgress(false);

    // 如果是输入框，则不立即跳转
    if (isInput) {
      return;
    }

    history.push(`/questionAnswer/home/${questionnaireUuid}/basicInfo/${currentRouteIndex + 1}`);
  };

  useEffect(() => {
    if (isNeedSaveBasicInfo) {
      run(userInfo);
    }

    return () => {
      dontNeedSaveBasicInfo();
    };
  }, [isNeedSaveBasicInfo]);

  /**
   * 组件数组
   */
  // FIXME： 因为只执行一次即可。所以应该使用 useEffect []
  const basicRouteComponentArray = initBasicRouteComponentArray(
    userInfo,
    onChange
  );
  /** 当前路由对象 */
  const currentRoute = basicRouteComponentArray.find(
    (element) => element.name === routerKeysArr[currentRouteIndex]
  );

  /**
   * 路由范围
   */
  useCheckUserInfoRange(
    currentRouteIndex,
    routerKeysArrLength,
    questionnaireUuid,
  );

  return (
    <div>
      <div className={questionnaireStyle['basic-information']}>
        <h1>基本信息填写</h1>
        <p>问卷将采用匿名方式， 您的回答我们会绝对保密，请根据真实情况认真填写。</p>
      </div>
      <div className={questionnaireStyle['basic-question']}>
        {currentRoute?.component}
      </div>
      <Footer
        userInfo={userInfo}
        routerKeysArr={routerKeysArr}
        questionnaireUuid={questionnaireUuid}
        currentRouteIndex={currentRouteIndex}
        isInSelectProgress={isInSelectProgress}
        needSaveBasicInfo={needSaveBasicInfo}
      />
    </div>
  );
};

export default BasicInfo;
